class TaskController < ApplicationController
  # 共通レイアウト定義
  layout "mainpage", :except=>[:block_list, :block_infolist, :dlg_index, :dlg_new, :dlg_edit, :dlg_create, :dlg_update, :dlg_destroy, :dlg_report]

  # フィルタ定義
  before_filter :login_required, :except=>[:sync_air] # ログインチェック

  # 追加ヘルパー定義
  helper :project

  # コントローラー使用のヘルパー定義
  include ApplicationHelper
  include ProjectHelper
  include TaskHelper


  #
  #=== タスク一覧表示
  #
  #ログイン中のユーザが担当となっているタスクの一覧を取得して表示する．
  #
  #同時にその他の担当者も取得する
  #
  def block_list
    #-----------------------------
    # ログイン中ユーザーが担当している
    # タスクのリストを取得
    # ※担当者、構成データも同時に取得
    #-----------------------------
    conditions = "dat_projects.valid_flg = 1 AND dat_projectusers.user_id = #{session['user']['id']}"
    if ! params[:project_id].nil?
      conditions += " AND dat_projectcomps.project_id = #{params[:project_id]}"
    end
    
    opt = {
      :conditions => conditions,
      :include    => [{:dat_taskusers=>:dat_projectuser}, {:dat_projectcomp=>:dat_project}], 
      :order      => "dat_tasks.id desc"
    }
    @tasks = DatTask.find(:all, opt)
  end

  #
  #タスクコントローラのデフォルトアクション
  def index
  end

  #
  #=== タスク完了登録アクション
  #
  #タスクを完了状態に更新する
  #
  def update_complete
    unless params[:task].nil?
      #-----------------------------
      # 登録済みのタスクを取得する
      #-----------------------------
      task = DatTask.find(params[:task][:id])
      #-----------------------------
      # 属性値設定
      #-----------------------------
      if task.progress_kbn != 3
        # 完了扱いに変更
        task.progress_kbn = 3
      else
        # 現在、完了の場合は、元に戻す
        task.progress_kbn = 0 ;
      end
      #-----------------------------
      # タスク情報保存
      #-----------------------------
      unless task.save
        result_for_json( false, 'update_complete error', {} )
        return
      end
    end
    render :text => result_for_json(true, '', {})
  end

  #
  #タスク編集ダイアログのためのデフォルトアクション
  #
  def dlg_index
  end

  #
  #タスク新規作成（ダイアログ用）
  #
  #空のタスクを生成し，タスク新規情報としてJSON形式で返す
  #* task_kbn: 1をセット(タスクのtask_kbnが1であるため)
  #
  def dlg_new
    #-----------------------------
    # 新規タスクオブジェクト生成
    #-----------------------------
    @task = DatTask.new
    #-----------------------------
    # 新規プロジェクト構成データオブジェクト生成
    # ※分類パラメータを初期設定（:dlg_tsk_edit_comp）
    #-----------------------------
    @projectcomp = DatProjectcomp.new(params[:dlg_tsk_edit_comp])
    @projectcomp.task_kbn = "1" ;

    #-----------------------------
    # 参加ユーザー情報の取得
    #-----------------------------
    # プロジェクト参加ユーザーリストを取得
    projectusers = object_for_projectusers(@projectcomp.project_id)
    # タスク参加ユーザーリストを取得
    taskusers = object_for_taskusers(@task.id)

    # 依頼者はログインユーザーデフォルト
    projectuser = DatProjectuser.find_by_user_id_and_project_id( session['user']['id'], @projectcomp.project_id )
#    projectuser = DatProjectuser.find_by_user_id(session['user']['id'])
    @task.client_user_id = projectuser.id

    #-----------------------------
    # JSONデータ生成
    #-----------------------------
    result  = {
      :task         => @task.attributes,
      :projectcomp  => @projectcomp.attributes,
      :projectusers => projectusers,
      :taskusers    => taskusers
    }
    render :text => result_for_json(true, '', result)
  end

  #
  #=== タスク編集ダイアログ
  #
  #指定されたタスクのデータを取得し，json形式で返却する
  #
  def dlg_edit
    if params[:dlg_tsk_edit_comp][:id].nil? || params[:dlg_tsk_edit_comp][:id] == ""
      #-----------------------------
      # IDが指定されていない場合、新規作成処理へリダイレクト
      #-----------------------------
      redirect_to :action => 'dlg_new'
    else
      #-----------------------------
      # 登録済みプロジェクト構成情報を取得
      # ※プロジェクト、タスク情報も同時に取得
      #-----------------------------
      opt = {
        :conditions => [" dat_projectcomps.id = ? ", params[:dlg_tsk_edit_comp][:id]],
        :include    => [:dat_project, :dat_task]
      }
      @projectcomp = DatProjectcomp.find(:first, opt)
      @task        = @projectcomp.dat_task
      #-----------------------------
      # 参加ユーザー情報の取得
      #-----------------------------
      # プロジェクト参加ユーザーリストを取得
      if @task
        projectusers = object_for_projectusers(@projectcomp.project_id)
        # タスク参加ユーザーリストを取得
        taskusers = object_for_taskusers(@task.id)
      end
      #-----------------------------
      # JSONデータ生成
      #-----------------------------
      result  = {
        :task         => @task ? @task.attributes : nil,
        :projectcomp  => @projectcomp.attributes,
        :projectusers => projectusers,
        :taskusers    => taskusers
      }
      render :text => result_for_json(true, '', result)
    end
  end

  #
  #=== タスクの新規作成
  #
  #フォームから渡されたパラメータを元にプロジェクトアイテムを新規作成し，
  #同時にタスクを作成する．
  #
  def dlg_create
    session_user_id = session["user"]["id"] 
    #-----------------------------
    # 新規プロジェクト構成データ生成
    #-----------------------------
    # フォームパラメータから新規プロジェクト構成オブジェクトを生成
    @projectcomp = DatProjectcomp.new(params[:dlg_tsk_edit_comp])
    @projectcomp.task_kbn = "1" ;
    @projectcomp.create_user_id = session_user_id
    @projectcomp.update_user_id = session_user_id
    @projectcomp.last_operation_kbn = 2

    #-----------------------------
    # 新規タスクデータ生成
    #-----------------------------
    # フォームパラメータから新規タスクオブジェクトを生成
    @task = DatTask.new( params[:dlg_tsk_edit_task] )
    @task.create_user_id = session_user_id
    @task.update_user_id = session_user_id
    @task.last_operation_kbn = 2
    @projectcomp.dat_task = @task

    #-----------------------------
    # 追加位置（行番号）決定
    #-----------------------------
    if ! params[:dlg_tsk_edit_base_id].nil? && ! params[:dlg_tsk_edit_base_id].empty?
      # 基準となるプロジェクト構成IDが指定されている場合
      # 基準データの後ろに追加
      base_projectcomp = DatProjectcomp.find(params[:dlg_tsk_edit_base_id])
      @projectcomp.line_no = base_projectcomp.line_no + 1
    else
      # 基準となるプロジェクト構成IDが指定されていない場合
      # プロジェクトの最後尾に追加
      max_line_no = DatProjectcomp.maximum( :line_no,
                                            :conditions=>["project_id = ? ", @projectcomp.project_id]
                                          )
      max_line_no = 0 if max_line_no.nil?
      @projectcomp.line_no = max_line_no + 1
    end

    #-----------------------------
    # タスク担当者生成
    #-----------------------------
    # タスクユーザー指定時、タスクユーザーオブジェクトを生成
    if ! params[:dlg_tsk_edit_taskusers].nil?
      for puser in params[:dlg_tsk_edit_taskusers][:projectuser_id]
        # buildにて生成し、ここでは保存しない
        taskuser = @task.dat_taskusers.build(:projectuser_id=>puser)
        taskuser.create_user_id = session_user_id
      end
    end

    #-----------------------------
    # プロジェクト構成データ保存実施
    #-----------------------------
    if ! @projectcomp.save
      message = error_message_to_string(@projectcomp, {:item_name=>app_localized_message(:label, :task_name)})
      unless @task.errors.empty?
        message += "\n" unless message == ""
        message += error_message_to_string(@task)
      end
      render :text => result_for_json( false, message, {} )
      return
    end

    #-----------------------------
    # 行番号更新
    #-----------------------------
    if ! params[:dlg_tsk_edit_base_id].nil? && ! params[:dlg_tsk_edit_base_id].empty?
      # 間に挿入した場合、以降の構成データの行番号をずらす
      if ! DatProjectcomp.update_all(" line_no = line_no + 1 ", 
                                   [ "project_id = ? AND line_no >= ? AND id <> ? ",
                                       @projectcomp.project_id,
                                       @projectcomp.line_no,
                                       @projectcomp.id ]
                                     )
        # ????? エラー処理 ????? 
        @projectcomp.destroy
        render :text => result_for_json( false, app_localized_message(:error, :task_lineno_save_error), {} )
        return
      end
    end

    #-----------------------------
    # JSONデータ生成
    #-----------------------------
    result  = {
      :resulthtml   => ""
    }
    render :text => result_for_json(true, '', result)
  end

  #
  #=== タスク更新
  #
  #指定されたタスクのデータをフォームパラメータを元に更新する
  #
  def dlg_update
    session_user_id = session["user"]["id"] 
    #-----------------------------
    # 登録済みオブジェクトを取得
    #-----------------------------
    @projectcomp = DatProjectcomp.find(:first,
                          :conditions => [" dat_projectcomps.id = ? ", params[:dlg_tsk_edit_comp][:id]],
                          :include =>[{:dat_task=>[:dat_taskusers]}] )
    @projectcomp.update_user_id = session_user_id
    @projectcomp.last_operation_kbn = 3
    @task = @projectcomp.dat_task
    @task.update_user_id = session_user_id
    @task.last_operation_kbn = 3

    #-----------------------------
    # タスク担当者生成
    #-----------------------------
    # タスクユーザー指定時、タスクユーザーオブジェクトを生成
    @task.dat_taskusers.clear  #一旦削除
    unless params[:dlg_tsk_edit_taskusers].nil?
      for puser in params[:dlg_tsk_edit_taskusers][:projectuser_id]
        # buildにて生成し、ここでは保存しない
        taskuser = @task.dat_taskusers.build(:projectuser_id=>puser)
        taskuser.create_user_id = session_user_id
      end
    end

    #-----------------------------
    # プロジェクト構成データ保存実施
    #-----------------------------
    #params[:dlg_tsk_edit_comp].delete(:id);
    @projectcomp.dat_task.update_attributes(params[:dlg_tsk_edit_task])
    unless @projectcomp.update_attributes(params[:dlg_tsk_edit_comp])
      # ????? エラー処理 ????? 
      message = error_message_to_string(@projectcomp, 
                                        {:item_name=>app_localized_message(:label, :task_name)})
      logger.debug @projectcomp.errors.inspect
      render :text => result_for_json( false, message, {} )
      return
    end
    #-----------------------------
    # タスクデータ保存実施
    #-----------------------------
    unless @task.update_attributes(params[:dlg_tsk_edit_task])
      # ????? エラー処理 ????? 
      message = error_message_to_string(@task)
      render :text => result_for_json( false, message, {} )
      return
    end

    #-----------------------------
    # JSONデータ生成
    #-----------------------------
    result  = {
      :resulthtml   => ""
    }
    render :text => result_for_json(true, '', result)
  end

  #
  #=== タスクの削除
  #
  #指定されたプロジェクトアイテムを削除する．
  #関連指定されたタスクも同時に削除される．
  #
  def dlg_destroy
    unless DatProjectcomp.destroy(params[:dlg_tsk_edit_comp][:id])
      render :text => result_for_json(false, app_localized_message(:error, :task_destroy_error), {})
    else
      result  = {
        :resulthtml => ""
      }
      render :text => result_for_json( true, '', result )
    end
  end


  #
  #=== タスクの進捗報告ダイアログ
  #
  #タスク報告ダイアログのためのアクション
  #
  def dlg_report
  end

  #
  #=== 進捗編集ダイアログ
  #
  #指定されたタスク進捗報告データを取得して，編集ダイアログを表示する
  #
  def dlg_report_edit
    if params[:dlg_tsk_report_task][:id].nil? || params[:dlg_tsk_report_task][:id] == ""
      render :text => result_for_json(false, '', result)
    else
      #-----------------------------
      # 登録済みタスク情報を取得
      # ※プロジェクト構成情報も同時に取得
      #-----------------------------
      opt = {
        :conditions => [" dat_tasks.id = ? ", params[:dlg_tsk_report_task][:id]],
        :include    => [:dat_projectcomp]
      }
      @task = DatTask.find(:first, opt)
      @projectcomp = @task.dat_projectcomp
  
      @task.report_date = Date.today if @task.report_date.nil?
      
      # JSONデータ生成
      result  = {
        :task        => @task.attributes,
        :projectcomp => @projectcomp.attributes
      }
      render :text => result_for_json(true, '', result)
    end
  end

  #
  #=== タスク報告を行う
  #
  #指定されたタスクに対する進捗報告を行う．
  #進捗報告新規作成，または更新する
  #
  def dlg_report_update
    session_user_id = session["user"]["id"] 
    #-----------------------------
    # 登録済みオブジェクトを取得
    #-----------------------------
    opt = {
      :conditions => [" dat_tasks.id = ? ", params[:dlg_tsk_report_task][:id]],
      :include    => :dat_projectcomp
    }
    @task = DatTask.find(:first, opt)
    @task.update_user_id = session_user_id
    @task.last_operation_kbn = 4
    @task.dat_projectcomp.last_operation_kbn = 4

    #-----------------------------
    # タスクデータ保存実施
    #-----------------------------
    if params[:dlg_tsk_report_task][:progress_kbn].nil?
      params[:dlg_tsk_report_task][:progress_kbn] = 0
    end
    unless @task.update_attributes(params[:dlg_tsk_report_task])
      # ????? エラー処理 ????? 
      message = error_message_to_string(@task)
      render :text => result_for_json(false, message, {})
    else
      result = {
        :resulthtml => ""
      }
      render :text => result_for_json( true, '', result )
    end
  end




  #
  #=== Airアプリ同期用
  #
  #Airアプリケーションとデータの同期を行う．
  #
  def sync_air()
    case request.method
      when :post
        json = params[:json]
        data = ActiveSupport::JSON.decode(json)
        logger.debug data.inspect
        dat_projectcomps = data['dat_projectcomps']
        dat_tasks        = data['dat_tasks']
        dat_task_users   = data['dat_taskusers']
        logger.debug dat_task_users.inspect
        
        if dat_projectcomps
          DatProjectcomp.transaction do
            dat_projectcomps.each do |comp|
              comp_id  = comp['id']
              local_id = comp['local_id']
              _task = nil
              dat_tasks.each do |task|
                if comp_id && task['project_tree_id'] == comp_id
                  _task = task
                elsif local_id && task['project_tree_id'] == local_id
                  _task = task
                end
              end
              comp[:task] = _task
              sync_air_for_task(comp, dat_task_users)
            end
          end
        end
      else
        # do nothing
    end
    
    project_id = data['project_id']
    
    dat_projectcomps = DatProjectcomp.find(:all, {
      :conditions=>["project_id = ? and task_kbn = 1", project_id]
    })
    _dat_projectcomps = dat_projectcomps.map do |comp|
      _comp = comp.attributes
      #_comp['complete_date'] = comp.complete_date.strftime('Y/m/d')
      #_comp['start_date']    = comp.start_date.strftime('Y/m/d')
      #_comp['end_date']      = comp.end_date.strftime('Y/m/d')
      #_comp
    end
    dat_tasks = DatTask.find(:all, {
      :conditions => ["dat_projectcomps.project_id = ?", project_id],
      :include    => [:dat_projectcomp]
    })
    _dat_tasks = dat_tasks.map do |task|
      _task = task.attributes
      _task['complete_date'] = task.complete_date.strftime('%Y/%m/%d') if task.complete_date
      _task['start_date']    = task.start_date.strftime('%Y/%m/%d') if task.start_date
      _task['end_date']      = task.end_date.strftime('%Y/%m/%d') if task.end_date
      _task
    end
    dat_taskusers = DatTaskuser.find(:all, {
      :conditions => ["dat_projectcomps.project_id = ?", project_id],
      :include    => [{:dat_task => :dat_projectcomp}]
    })
    _dat_taskusers = dat_taskusers.map do |user|
      _user = user.attributes
    end
    
    
    r = {
      :dat_projectcomps => _dat_projectcomps,
      :dat_tasks        => _dat_tasks,
      :dat_taskusers    => _dat_taskusers,
    }
    render :text => result_for_json(true, '', r)
  end


  private

  def sync_air_for_task(dat_projectcomp, users)
    r = false
    # 登録済みオブジェクトを取得
    is_new = false
    if dat_projectcomp.id
      opt = {
        :conditions => [" dat_projectcomps.id = ? ", dat_projectcomp['id']],
        #:include    => [{:dat_task => [:dat_taskusers]}]
        :include    => [:dat_task]
      }
      projectcomp = DatProjectcomp.find(:first, opt)
      task        = projectcomp.dat_task
    else
      is_new = true
      projectcomp = DatProjectcomp.new
      task        = DatTask.new
    end
    task_param = dat_projectcomp[:task]
    
    updated_on = Time.parse(task_param['updated_on'])
    logger.debug updated_on
    if is_new or updated_on >= projectcomp.updated_on
      projectcomp.item_name      = dat_projectcomp['item_name']
      projectcomp.class_word1    = dat_projectcomp['class_word1']
      projectcomp.class_word2    = dat_projectcomp['class_word2']
      projectcomp.class_word3    = dat_projectcomp['class_word3']
      projectcomp.update_user_id = dat_projectcomp['update_user_id']
      projectcomp.last_operation_kbn = dat_projectcomp['last_operation_kbn']
      
      task.update_user_id = task_param['update_user_id']
      task.main_user_id   = task_param['main_user_id']
      task.client_user_id = task_param['client_user_id']
      task.memo           = task_param['memo']
      task.result         = task_param['result']
      task.tani_kbn       = task_param['tani_kbn']
      task.progress_kbn   = task_param['progress_kbn']
      task.progress_rate  = task_param['progress_rate']
      task.exp_power      = task_param['exp_power']
      task.plan_power     = task_param['plan_power']
      task.fcas_power     = task_param['fcas_power']
      task.priority_kbn   = task_param['priority_kbn']
      task.complete_date  = Date.parse(task_param['complete_date'])
      task.start_date     = Date.parse(task_param['start_date'])
      task.end_date       = Date.parse(task_param['end_date'])
      logger.debug task.inspect
=begin
      task.dat_taskusers.clear  #一旦削除
      if users
        users.each do |user|
          if user['task_id'] == task['id']
            taskuser = task.dat_taskusers.build({:projectuser_id => user['projectuser_id'], :create_user_id => task_param['update_user_id']})
          end
        end
      end
=end
      if projectcomp.save and task.save
        r = true
      end
    else
      r = true
    end
    return r
  end

end